/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Planificacion.Algoritmo;

import java.io.BufferedReader;
import java.io.Console;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;


/**
 *
 * @author Tatooine
 */

public class Lector {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        File archivo1 = null;
        File archivo2 = null;
        FileReader fr1 = null;
        FileReader fr2 = null;
        BufferedReader br1 = null;
        BufferedReader br2 = null;
        String linea;
        int NumMotos=0;
        int NumAutos=0;
        int VelocMoto=0;
        int VelocAuto=0;
        int CapMotos=0;
        int CapAutos=0;
        int CostoKmMoto=0;
        int CostoKmAuto=0;
        int CostoProducto=0;
        int NumPedidos=8;
        int CostoRetraso=20;
        Coordenada Origen=new Coordenada(0,0);
        ArrayList<Integer> vehiculos;//Almacena 0 si moto, 1 si auto
        
        try {
         // Apertura del fichero y creacion de BufferedReader para poder
         // hacer una lectura comoda (disponer del metodo readLine()).
            
         archivo1 = new File ("D:\\vehicle.txt");
         archivo2 = new File ("D:\\mapa.txt");
         fr1 = new FileReader (archivo1);
         fr2 = new FileReader (archivo2);
         br1= new BufferedReader(fr1);
         br2= new BufferedReader(fr2);
         
         Mapa map=new Mapa();
         linea=br2.readLine();
         String[] arrayL=linea.split(" ");
         int MapaDimension=Integer.parseInt(arrayL[0]);
         map.setDimension(MapaDimension);
         int PesoArista=Integer.parseInt(arrayL[1]);
         map=ProcesaMapa(MapaDimension,PesoArista);
         
         linea=br1.readLine();
         arrayL=linea.split(" ");
         NumMotos=Integer.parseInt(arrayL[0]);
         NumAutos=Integer.parseInt(arrayL[1]);
         
         linea=br1.readLine();
         arrayL=linea.split(" ");
         VelocMoto=Integer.parseInt(arrayL[0]);
         VelocAuto=Integer.parseInt(arrayL[1]);
         
         linea=br1.readLine();
         arrayL=linea.split(" ");
         CapMotos=Integer.parseInt(arrayL[0]);
         CapAutos=Integer.parseInt(arrayL[1]);
         
         linea=br1.readLine();
         arrayL=linea.split(" ");
         CostoKmMoto=Integer.parseInt(arrayL[0]);
         CostoKmAuto=Integer.parseInt(arrayL[1]);
         
         vehiculos=AlmacenaVehiculo(NumMotos,NumAutos); //Llena de 0 y 1 array de vehiculos, 0 moto y 1 si auto
         
         CostoProducto=Integer.parseInt(br1.readLine());
         ArrayList<Producto> ArrayProd = new ArrayList();//Array para almancenar los productos
         while((linea=br1.readLine())!=null){
           arrayL=linea.split(" ");
           int IdPedido=Integer.parseInt(arrayL[0]);
           int NumProductos=Integer.parseInt(arrayL[1]);
           int PosX=Integer.parseInt(arrayL[2]);
           int PosY=Integer.parseInt(arrayL[3]);
           int TiempoRest=Integer.parseInt(arrayL[4]);
           Coordenada destino=new Coordenada(PosX, PosY);
             for (int i = 0; i < NumProductos; i++) {
                 Producto Prod=new Producto(IdPedido, destino, CostoProducto, TiempoRest);
                 ArrayProd.add(Prod);
             }
         }
            for (int i = 0; i < 1; i++) {
                GRASP AlgGRASP=new GRASP(NumAutos, NumMotos, VelocAuto, VelocMoto, CapMotos, CapAutos, CostoKmAuto, CostoKmMoto, CostoProducto, Origen,ArrayProd,NumPedidos,CostoRetraso);
                //AlgGRASP.MostrarContenidoVariables();
                AlgGRASP.EjecutaGRASP();
            }
            
//         double alfa1=0.12;
//         double alfa2=0.65;
//         GRASP(ArrayProd,Origen,NumMotos,NumAutos,VelocMoto,VelocAuto,CapMotos,CapAutos,CostoKmMoto,CostoKmAuto,alfa1,alfa2);
//            for (Producto producto : ArrayProd) {
//                System.out.println(producto.getIdPedido()+" ("+producto.getDestino().getX()+","+producto.getDestino().getY()+") "+producto.getCosto()+" "+producto.getTiempoRestante());
//            }
      }
      catch(Exception e){
         e.printStackTrace();
      }finally{
         // En el finally cerramos el fichero, para asegurarnos
         // que se cierra tanto si todo va bien como si salta 
         // una excepcion.
         try{                    
            if( null != fr1 ){   
               fr1.close();
               fr2.close();
            }                  
         }catch (Exception e2){ 
            e2.printStackTrace();
         }
      }
    }
    //------------------------------------------------------------------------------------------------------------------------------
        public static void GRASP(ArrayList<Producto> ArrayProd,Coordenada Origen,int NumMotos,int NumAutos,int VelMoto,int VelAuto,int CapacMoto,int CapacAuto,int CostoKmMoto,int CostoKmAuto,double alfa1,double alfa2){
            //El array vehiculos almacena 0 y 1, 0 para moto, 1 para auto
            ArrayList<Vehículo> ArrayVehiculos=new ArrayList();
            ArrayVehiculos=InicializaArrayVehiculos(NumMotos,NumAutos,VelMoto,VelAuto,CapacMoto,CapacAuto,CostoKmMoto,CostoKmAuto,ArrayProd.size(),Origen);//ArrayProd.size me da Número de Productos
            
            int Distancia=0;//Distancia del origen a destino, se guaradara por cada producto. Por corrida.
            for (Producto Prod  : ArrayProd) {//Recorreré todos los productos para asignarlos a vehículo y luego darle un turno
                //System.out.println(Prod.getIdPedido());
                //Calculo distancia entre origen y destino
                int IdPedidoProd=Prod.getIdPedido();
                int CostoProd=Prod.getCosto();
                Coordenada Destino=Prod.getDestino();
                int TiempoRest=Prod.getTiempoRestante();
                ArrayList<Coordenada> c=new ArrayList();
                c.add(Origen);
                c.add(Prod.getDestino());
                RespuestaVoraz PruebaVoraz=new RespuestaVoraz();
                PruebaVoraz=PruebaVoraz.Voraz(false, c);
                
                Distancia=PruebaVoraz.distancia.get(0);//como solo obtengo una distancia, es 0 el primer indice. El que necesito
                
                for (Vehículo vehiculo : ArrayVehiculos) {//Se recorre cada vehículo y se ejecuta FO=Ganancia/(Distancia*costoKMVehiculo)
                    int NumProdVehiculo=vehiculo.getNumProdContiene();
                    int DistAcumVehiculo=vehiculo.getDistanciaAcumulada();//Distancia Acumulada hasta ese momento recorrida
                    //En la FO se le agrega a la DistAcumVehiculo, la Distancia encontrada en el punto anterior(origen,destino)
                    //Y a NumProdVehiculo le agrego el producto solo para evaluar,sumo 1 ya que el vehiculo lo podria llevar pero será evaluado
                    double FO=((NumProdVehiculo+1)*CostoProd*1.0)/((DistAcumVehiculo+Distancia)*vehiculo.getCostoXKm());

                    vehiculo.setFO(FO);//Actualizo FO en objetivo
                    
                }//Al acabar el FOR el ArrayAuxFO tiene todas las FO para todos los vehiculos
                //Ahora se arma la lista de candidatos
                ArrayList<Integer> ArrayAux;//Se guardará los IdVehiculos de lista RCL
                ArrayAux=RCLAsignacion(ArrayVehiculos,alfa1);//obtengo un array de enteros que son los Id de los vehículos
                //Ahora se hará un aleatorio de esta lista para elegir el vehiculo al cual se le asignará el producto
                int IdVehiculoElegido=Aleatorio(ArrayAux);
                //El indice del vehiculo es el id-1, asi que seteamos ese indice 
                Vehículo v1=ArrayVehiculos.get(IdVehiculoElegido-1);
                v1.setDistanciaAcumulada(v1.getDistanciaAcumulada()+Distancia);
                v1.setNumProdContiene(v1.getNumProdContiene()+1);
                //SEGUNDA RELAJACIÓN
                //FO= Sumatoria Ganancia-Tretraso*KcostoRetrasoHora
                //ahora que ya se agrego un producto mas y se le sumo la distancia a la distancia acumulada al vehiculo
                //se procede a elegir en que turno irá ese producto. Recordar que son como máximo (NumProducto-1) turnos en el peor de los casos
                
            }
            for (Vehículo vehiculo : ArrayVehiculos) {
                System.out.println((vehiculo.getDistanciaAcumulada()*vehiculo.getCostoXKm()));
            }
            
        }
        //------------------------------------------------------------------------------------------------------------------------
        public static int Aleatorio(ArrayList<Integer> lista){
            int tamanho=lista.size();//tamanho de lista entre la cual se elegirá uno
            int numSorteado;
            int IdVehiculoElegido;
            Random r=new Random();
            numSorteado=r.nextInt(tamanho);
            IdVehiculoElegido=lista.get(numSorteado);
            return IdVehiculoElegido;
        }
        //------------------------------------------------------------------------------------------------------------------------
        public static ArrayList<Integer> RCLAsignacion(ArrayList<Vehículo> lista,double alfa){
            //Como lo que queremos es maximizar ganancia, entonces ordenamos de mayor a menor FO el array de vehiculos
            ArrayList<Vehículo> listaAux=new ArrayList();
            
            for (Vehículo vehículo : lista) {//copia a un nuevo array, no recuerdo si en caso ordenara afectara cuando salga de este metodo
                listaAux.add(vehículo);
            }

            double beta;
            double tau;
            Collections.sort(listaAux,Collections.reverseOrder());//ordeno ascendetemente la lista de vehiculos
            
            beta=listaAux.get(0).getFO();//mejor, 
            tau=listaAux.get(listaAux.size()-1).getFO();//peor, 
            //double rangoFinal=beta-alfa*(beta-tau);
            double rangoFinal=beta-alfa*(beta-tau);
            //RCL=beta<= lista<=beta+alfa*(tau-beta)
            //mi rango estará entre beta y rangoFinal=beta+alfa*(tau-beta);
            //en el array que arrojaré solo guardaré los id de los vehiculos q cumplen la condición
            ArrayList<Integer> RCL=new ArrayList();
            RCL.clear();
            for (Vehículo vehiculo : listaAux) {
                if(vehiculo.getFO()<=beta && vehiculo.getFO()>=rangoFinal) RCL.add(vehiculo.getIdVehiculo());
            }
            return RCL;
        }
        //------------------------------------------------------------------------------------------------------------------------        
        public static ArrayList InicializaArrayVehiculos(int NumMotos,int NumAutos,int VelMoto,int VelAuto,int CapacMoto,int CapacAuto,int CostoKmMoto,int CostoKmAuto,int NumProductos,Coordenada Origen){
            ArrayList<Vehículo> lista= new ArrayList();
            int TotalVehiculos=NumMotos+NumAutos;
            for (int i = 0; i < TotalVehiculos; i++) {
                if(i<NumMotos) lista.add(new Vehículo(i+1,0, VelMoto, CapacMoto,CostoKmMoto,NumProductos,Origen));
                else lista.add(new Vehículo(i+1,1, VelAuto, CapacAuto,CostoKmAuto,NumProductos,Origen));
            }
//            for (Vehículo vehiculo : lista) {
//                System.out.println("Tipo: " + vehiculo.getTipo() + " Veloc: " + vehiculo.getVelocidad() + " Capac: "+vehiculo.getCapacidad()+" NumProd: "+vehiculo.getNumProdContiene());
//                for (Turno t1 : vehiculo.getTurnos()) {
//                    System.out.print(t1.getNumTurno()+" ");
//                }
//                System.out.println();
//            }
            return lista;
        }
        
        //------------------------------------------------------------------------------------------------------
        public static ArrayList AlmacenaVehiculo(int NumMotos,int NumAutos){
            ArrayList<Integer> vehiculos=new ArrayList();
            int TotalVehiculos=NumMotos+NumAutos;
            for (int i = 0; i < TotalVehiculos; i++) {
                if(i<NumMotos) vehiculos.add(0);
                else vehiculos.add(1);
            }
            return vehiculos;
        }
        //--------------------------------------------------------------------------------------------------------
        public static Mapa ProcesaMapa(int MapaDimension,int PesoArista){
            Mapa map=new Mapa();
            char direccion;
            
            for (int i = 0; i <= MapaDimension; i++) {
                for (int j = 0; j <MapaDimension; j++) {
                    int PosX;
                    int PosY;
                    Coordenada posicion;
                    
                    //arriba
                    direccion='U';
                    if(j-1>=0){ 
                        posicion=new Coordenada(i, j);
                        map.setValue(posicion, direccion, PesoArista);
                    }
                    //izquierda
                    direccion='L';
                    if(i-1>=0){
                        posicion=new Coordenada(i, j);
                        map.setValue(posicion, direccion, PesoArista);
                    }
                    //abajo
                    direccion='D';
                    if(j+1<=MapaDimension){
                        posicion=new Coordenada(i, j);
                        map.setValue(posicion, direccion, PesoArista);
                    }
                    //derecho
                    direccion='R';
                    if(i+1<=MapaDimension){
                        posicion=new Coordenada(i, j);
                        map.setValue(posicion, direccion, PesoArista);
                    }
                }
                    
                
            }
//            Coordenada posicion=new Coordenada(100, 120);
//            int value=map.getValue(posicion,'U');
//            System.out.println(value);
            return map;
        }
//        for (int i = 0; i < 4; i++) {
//            Coordenada pos=new Coordenada(i, i+1);
//            ArrayProd.add(new Producto(i,pos,20+i));
//        }
//        System.out.println(ArrayProd.size());
//        for (Producto p1:ArrayProd){
//            System.out.println(p1.getIdPedido() + " (" + p1.getDestino().getX() +","+p1.getDestino().getY()+")");
//        }
        
}
   